home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / DirectPlay / Tutorials / Tut07_LobbyLaunch / LobbyLaunch.cpp next >
C/C++ Source or Header  |  2001-10-08  |  32KB  |  971 lines

  1. //----------------------------------------------------------------------------
  2. // File: LobbyLaunch.cpp
  3. //
  4. // Desc: This simple program builds upon the last tutorial and adds lobby 
  5. //       launching
  6. //
  7. // Copyright (c) 2000-2001 Microsoft Corp. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define INITGUID
  10. #define _WIN32_DCOM
  11. #include <stdio.h>
  12. #include <dplay8.h>
  13. #include <dplobby8.h>
  14.  
  15.  
  16.  
  17. //-----------------------------------------------------------------------------
  18. // App specific structures 
  19. //-----------------------------------------------------------------------------
  20. struct HOST_NODE
  21. {
  22.     DPN_APPLICATION_DESC*   pAppDesc;
  23.     IDirectPlay8Address*    pHostAddress;
  24.     WCHAR*                  pwszSessionName;
  25.  
  26.     HOST_NODE*              pNext;
  27. };
  28.  
  29.  
  30. //-----------------------------------------------------------------------------
  31. // Global variables
  32. //-----------------------------------------------------------------------------
  33. IDirectPlay8Peer*                   g_pDP               = NULL;
  34. IDirectPlay8LobbiedApplication*     g_pLobbyApp         = NULL;
  35. IDirectPlay8Address*                g_pDeviceAddress    = NULL;
  36. IDirectPlay8Address*                g_pHostAddress      = NULL;
  37. DPNHANDLE                           g_hLobbyHandle      = NULL;
  38. BOOL                                g_bLobbyLaunched    = FALSE;
  39. BOOL                                g_bHost;
  40. BOOL                                g_bRegister         = FALSE;
  41. BOOL                                g_bUnRegister       = FALSE;
  42. WCHAR*                              g_wszPath           = NULL;
  43. HOST_NODE*                          g_pHostList         = NULL;
  44. CRITICAL_SECTION                    g_csHostList;
  45. DPNID                               g_dpnidLocalPlayer  = 0;
  46.  
  47.  
  48. // This GUID allows DirectPlay to find other instances of the same game on
  49. // the network.  So it must be unique for every game, and the same for 
  50. // every instance of that game.  // {C301FCED-E884-41a9-94D7-DE66943EC7DB}
  51. GUID g_guidApp = { 0xc301fced, 0xe884, 0x41a9, { 0x94, 0xd7, 0xde, 0x66, 0x94, 0x3e, 0xc7, 0xdb } };
  52.  
  53.  
  54. //-----------------------------------------------------------------------------
  55. // Function-prototypes
  56. //-----------------------------------------------------------------------------
  57. HRESULT WINAPI DirectPlayMessageHandler(PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer);
  58. HRESULT WINAPI LobbyAppMessageHandler(PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer);
  59. BOOL    IsServiceProviderValid(const GUID* pGuidSP);
  60. HRESULT InitDirectPlay();
  61. HRESULT CreateDeviceAddress();
  62. HRESULT CreateHostAddress(WCHAR* pwszHost);
  63. HRESULT HostSession();
  64. HRESULT EnumDirectPlayHosts();
  65. HRESULT ConnectToSession();
  66. HRESULT SendDirectPlayMessage();
  67. HRESULT Register();
  68. HRESULT UnRegister();
  69. HRESULT LobbyLaunch();
  70. void    CleanupDirectPlay();
  71.  
  72.  
  73. //-----------------------------------------------------------------------------
  74. // Miscellaneous helper functions
  75. //-----------------------------------------------------------------------------
  76. #define SAFE_DELETE(p)          {if(p) {delete (p);     (p)=NULL;}}
  77. #define SAFE_DELETE_ARRAY(p)    {if(p) {delete[] (p);   (p)=NULL;}}
  78. #define SAFE_RELEASE(p)         {if(p) {(p)->Release(); (p)=NULL;}}
  79.  
  80. #define USER_HOST       1
  81. #define USER_CONNECT    2
  82. #define USER_EXIT       1
  83. #define USER_SEND       2
  84.  
  85. #define CMDLINE_REGISTER    "register"
  86. #define CMDLINE_UNREGISTER  "unregister"
  87.  
  88.  
  89.  
  90.  
  91. //-----------------------------------------------------------------------------
  92. // Name: main()
  93. // Desc: Entry point for the application.  
  94. //-----------------------------------------------------------------------------
  95. int main(int argc, char* argv[], char* envp[])
  96. {
  97.     HRESULT                     hr;
  98.     int                         iUserChoice;
  99.     int                         i;
  100.  
  101.     // Init COM so we can use CoCreateInstance
  102.     CoInitializeEx(NULL, COINIT_MULTITHREADED);
  103.     InitializeCriticalSection(&g_csHostList);
  104.  
  105.     // Process the args
  106.     for (i = 1; i < argc, argv[i] != NULL; i++)
  107.     {
  108.         if( !(strcmp(CMDLINE_REGISTER, argv[i] ) ) )
  109.         {
  110.             g_bRegister = TRUE;
  111.             g_wszPath = new WCHAR[strlen(argv[0]) + 1];
  112.  
  113.             if( !g_wszPath)
  114.             {
  115.                 printf("Failed allocating string\n");
  116.                 goto LCleanup;
  117.             }
  118.  
  119.             MultiByteToWideChar(CP_ACP, 0, argv[0], -1, g_wszPath, strlen(argv[0]) + 1);
  120.         }
  121.         else if( !strcmp(CMDLINE_UNREGISTER, argv[i]))
  122.         {
  123.             g_bUnRegister = TRUE;
  124.         }
  125.         else if( !strcmp("-?", argv[i]))
  126.         {
  127.             printf("\nUsage:  register/unregister\n");
  128.             goto LCleanup;
  129.         }
  130.     }
  131.  
  132.     // Init the DirectPlay system
  133.     if( FAILED( hr = InitDirectPlay() ) )
  134.     {
  135.         printf("Failed Initializing DirectPlay:  0x%X\n", hr);
  136.         goto LCleanup;
  137.     }
  138.  
  139.     if( g_bRegister )
  140.     {
  141.         if( FAILED( hr = Register() ) )
  142.         {
  143.             printf("Failed To Register:  0x%X\n", hr);
  144.         }
  145.         goto LCleanup;
  146.     }
  147.     else if( g_bUnRegister )
  148.     {
  149.         if( FAILED( hr = UnRegister() ) )
  150.         {
  151.             printf("Failed To Unregister:  0x%X\n", hr);
  152.         }
  153.         goto LCleanup;
  154.     }
  155.  
  156.     // See if we were lobby launched or not
  157.     if( g_bLobbyLaunched )
  158.     {
  159.         if( FAILED( hr = LobbyLaunch() ) )
  160.         {
  161.             printf("Failed be Lobby Launched:  0x%X\n", hr);
  162.             goto LCleanup;
  163.         }
  164.     }
  165.     else
  166.     {
  167.         // Get the necessary user input on whether they are hosting or connecting
  168.         do
  169.         {
  170.             printf("Please select one.\n1.  Host\n2.  Connect\n");
  171.             scanf("%d", &iUserChoice);
  172.         } while (iUserChoice != USER_HOST && iUserChoice != USER_CONNECT);
  173.  
  174.  
  175.         if( FAILED( hr = CreateDeviceAddress() ) )
  176.         {
  177.             printf("Failed CreatingDeviceAddress:  0x%X\n", hr);
  178.             goto LCleanup;
  179.         }
  180.  
  181.         if( iUserChoice == USER_HOST)
  182.         {
  183.             if( FAILED( hr = HostSession() ) )
  184.             {
  185.                 printf("Failed Hosting:  0x%X\n", hr);
  186.                 goto LCleanup;
  187.             }
  188.         }
  189.         else
  190.         {
  191.             if( FAILED( hr = EnumDirectPlayHosts() ) )
  192.             {
  193.                 printf("Failed Enumerating Host:  0x%X\n", hr);
  194.                 goto LCleanup;
  195.             }
  196.  
  197.             if( FAILED( hr = ConnectToSession() ) )
  198.             {
  199.                 printf("Failed Connect to Host:  0x%X\n", hr);
  200.                 goto LCleanup;
  201.             }
  202.             else
  203.             {
  204.                 printf("\nConnection Successful.\n");
  205.             }
  206.         }
  207.     }
  208.     // Present User with Choices
  209.     do
  210.     {
  211.         printf("Please select one.\n1.  Exit\n2.  Send Data\n");
  212.         scanf("%d", &iUserChoice);
  213.  
  214.         if( iUserChoice == USER_SEND)
  215.         {
  216.             if( FAILED( hr = SendDirectPlayMessage() ) )
  217.             {
  218.                 printf("Failed To Send Data:  0x%X\n", hr);
  219.                 goto LCleanup;
  220.             }
  221.         }
  222.     } while (iUserChoice != USER_EXIT);
  223.    
  224.  
  225. LCleanup:
  226.     CleanupDirectPlay();
  227.  
  228.     // Cleanup COM
  229.     CoUninitialize();
  230.  
  231.     return 0;
  232. }
  233.  
  234.  
  235.  
  236.  
  237. //-----------------------------------------------------------------------------
  238. // Name: InitDirectPlay()
  239. // Desc: Initialize DirectPlay
  240. //-----------------------------------------------------------------------------
  241. HRESULT InitDirectPlay()
  242. {
  243.     HRESULT     hr = S_OK;
  244.  
  245.     // Create the IDirectPlay8Peer Object
  246.     if( FAILED( hr = CoCreateInstance(CLSID_DirectPlay8Peer, NULL, 
  247.                                     CLSCTX_INPROC_SERVER,
  248.                                     IID_IDirectPlay8Peer, 
  249.                                     (LPVOID*) &g_pDP ) ) )
  250.     {
  251.         printf("Failed Creating the IDirectPlay8Peer Object:  0x%X\n", hr);
  252.         goto LCleanup;
  253.     }
  254.  
  255.     // Create the IDirectPlay8LobbiedApplication Object
  256.     if( FAILED( hr = CoCreateInstance(CLSID_DirectPlay8LobbiedApplication, NULL, 
  257.                                     CLSCTX_INPROC_SERVER,
  258.                                     IID_IDirectPlay8LobbiedApplication, 
  259.                                     (LPVOID*) &g_pLobbyApp ) ) )
  260.     {
  261.         printf("Failed Creating the IDirectPlay8LobbiedApplication Object:  0x%X\n", hr);
  262.         goto LCleanup;
  263.     }
  264.  
  265.     // Init DirectPlay
  266.     if( FAILED( hr = g_pDP->Initialize(NULL, DirectPlayMessageHandler, 0 ) ) )
  267.     {
  268.         printf("Failed Initializing DirectPlay:  0x%X\n", hr);
  269.         goto LCleanup;
  270.     }
  271.     
  272.     // Init the Lobby interface
  273.     if( FAILED( hr = g_pLobbyApp->Initialize(NULL, LobbyAppMessageHandler, &g_hLobbyHandle, 0 ) ) )
  274.     {
  275.         printf("Failed Initializing Lobby:  0x%X\n", hr);
  276.         goto LCleanup;
  277.     }
  278.     else
  279.         g_bLobbyLaunched = (g_hLobbyHandle != NULL);
  280.     
  281.     // Ensure that TCP/IP is a valid Service Provider
  282.     if( FALSE == IsServiceProviderValid(&CLSID_DP8SP_TCPIP ) )
  283.     {
  284.         hr = E_FAIL;
  285.         printf("Failed validating CLSID_DP8SP_TCPIP");
  286.         goto LCleanup;
  287.     }
  288.  
  289. LCleanup:
  290.     return hr;
  291. }
  292.  
  293.  
  294.  
  295.  
  296. //-----------------------------------------------------------------------------
  297. // Name: IsServiceProviderValid()
  298. // Desc: Return TRUE if the service provider is valid
  299. //-----------------------------------------------------------------------------
  300. BOOL IsServiceProviderValid(const GUID* pGuidSP)
  301. {
  302.     HRESULT                     hr;
  303.     DPN_SERVICE_PROVIDER_INFO*  pdnSPInfo = NULL;
  304.     DWORD                       dwItems = 0;
  305.     DWORD                       dwSize = 0;
  306.  
  307.     hr = g_pDP->EnumServiceProviders(&CLSID_DP8SP_TCPIP, NULL, NULL, &dwSize, &dwItems, 0);
  308.  
  309.     if( hr != DPNERR_BUFFERTOOSMALL)
  310.     {
  311.         printf("Failed Enumerating Service Providers:  0x%x\n", hr);
  312.         goto LCleanup;
  313.     }
  314.  
  315.     pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
  316.  
  317.     if( FAILED( hr = g_pDP->EnumServiceProviders(&CLSID_DP8SP_TCPIP, NULL, pdnSPInfo, &dwSize, &dwItems, 0 ) ) )
  318.     {
  319.         printf("Failed Enumerating Service Providers:  0x%x\n", hr);
  320.         goto LCleanup;
  321.     }
  322.  
  323.     // There are no items returned so the requested SP is not available
  324.     if( dwItems == 0)
  325.     {
  326.         hr = E_FAIL;
  327.     }
  328.  
  329. LCleanup:
  330.     SAFE_DELETE_ARRAY(pdnSPInfo);
  331.     if( SUCCEEDED(hr) )
  332.         return TRUE;
  333.     else
  334.         return FALSE;
  335. }
  336.  
  337.  
  338.  
  339.  
  340. //-----------------------------------------------------------------------------
  341. // Name: DirectPlayMessageHandler
  342. // Desc: Handler for DirectPlay messages.  
  343. //-----------------------------------------------------------------------------
  344. HRESULT WINAPI DirectPlayMessageHandler(PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer)
  345. {
  346.     HRESULT     hr = S_OK;
  347.  
  348.     switch (dwMessageId)
  349.     {
  350.         case DPN_MSGID_ENUM_HOSTS_RESPONSE:
  351.         {
  352.             PDPNMSG_ENUM_HOSTS_RESPONSE     pEnumHostsResponseMsg;
  353.             const DPN_APPLICATION_DESC*     pAppDesc;
  354.             HOST_NODE*                      pHostNode = NULL;
  355.             WCHAR*                          pwszSession = NULL;
  356.  
  357.             pEnumHostsResponseMsg = (PDPNMSG_ENUM_HOSTS_RESPONSE) pMsgBuffer;
  358.             pAppDesc = pEnumHostsResponseMsg->pApplicationDescription;
  359.  
  360.             // Insert each host response if it isn't already present
  361.             EnterCriticalSection(&g_csHostList);
  362.  
  363.             for (pHostNode = g_pHostList; pHostNode; pHostNode = pHostNode->pNext)
  364.             {
  365.                 if( pAppDesc->guidInstance == pHostNode->pAppDesc->guidInstance)
  366.                 {
  367.                     // This host is already in the list
  368.                     pHostNode = NULL;
  369.                     goto Break_ENUM_HOSTS_RESPONSE;
  370.                 }
  371.             }
  372.  
  373.             // This host session is not in the list then so insert it.
  374.             pHostNode = new HOST_NODE;
  375.             if( pHostNode == NULL)
  376.             {
  377.                 goto Break_ENUM_HOSTS_RESPONSE;
  378.             }
  379.  
  380.             ZeroMemory(pHostNode, sizeof(HOST_NODE));
  381.  
  382.             // Copy the Host Address
  383.             if( FAILED( pEnumHostsResponseMsg->pAddressSender->Duplicate(&pHostNode->pHostAddress ) ) )
  384.             {
  385.                 goto Break_ENUM_HOSTS_RESPONSE;
  386.             }
  387.  
  388.             pHostNode->pAppDesc = new DPN_APPLICATION_DESC;
  389.  
  390.             if( pHostNode == NULL)
  391.             {
  392.                 goto Break_ENUM_HOSTS_RESPONSE;
  393.             }
  394.  
  395.             ZeroMemory(pHostNode->pAppDesc, sizeof(DPN_APPLICATION_DESC));
  396.             memcpy(pHostNode->pAppDesc, pAppDesc, sizeof(DPN_APPLICATION_DESC));
  397.  
  398.             // Null out all the pointers we aren't copying
  399.             pHostNode->pAppDesc->pwszSessionName = NULL;
  400.             pHostNode->pAppDesc->pwszPassword = NULL;
  401.             pHostNode->pAppDesc->pvReservedData = NULL;
  402.             pHostNode->pAppDesc->dwReservedDataSize = 0;
  403.             pHostNode->pAppDesc->pvApplicationReservedData = NULL;
  404.             pHostNode->pAppDesc->dwApplicationReservedDataSize = 0;
  405.             
  406.             if( pAppDesc->pwszSessionName)
  407.             {
  408.                 pwszSession = new WCHAR[wcslen(pAppDesc->pwszSessionName) + 1];
  409.                 
  410.                 if( pwszSession)
  411.                 {
  412.                     wcscpy(pwszSession, pAppDesc->pwszSessionName);
  413.                 }
  414.             }
  415.  
  416.             pHostNode->pwszSessionName = pwszSession;
  417.  
  418.             // Insert it onto the front of the list
  419.             pHostNode->pNext = g_pHostList ? g_pHostList->pNext : NULL;
  420.             g_pHostList = pHostNode;
  421.             pHostNode = NULL;
  422.  
  423. Break_ENUM_HOSTS_RESPONSE:
  424.             LeaveCriticalSection(&g_csHostList);
  425.  
  426.             if( pHostNode)
  427.             {
  428.                 SAFE_RELEASE(pHostNode->pHostAddress);
  429.  
  430.                 SAFE_DELETE(pHostNode->pAppDesc);
  431.  
  432.                 delete pHostNode;
  433.             }
  434.  
  435.             break;
  436.         }
  437.     
  438.         case DPN_MSGID_RECEIVE:
  439.         {
  440.             PDPNMSG_RECEIVE     pMsg;
  441.  
  442.             pMsg = (PDPNMSG_RECEIVE) pMsgBuffer;
  443.  
  444.             printf("\nReceived Message:  %S\n", (WCHAR*)pMsg->pReceiveData);
  445.             break;
  446.         }
  447.     
  448.         case DPN_MSGID_HOST_MIGRATE:
  449.         {
  450.             PDPNMSG_HOST_MIGRATE    pHostMigrateMsg;
  451.  
  452.             pHostMigrateMsg = (PDPNMSG_HOST_MIGRATE) pMsgBuffer;
  453.  
  454.             printf("\nHost Migration Has Occured.\n");
  455.  
  456.             // See if we are the new host
  457.             if( pHostMigrateMsg->dpnidNewHost == g_dpnidLocalPlayer)
  458.                 printf("You are the New Host\n");
  459.             else
  460.                 printf("DPNID of New Host is %d\n", pHostMigrateMsg->dpnidNewHost);
  461.  
  462.             break;
  463.         }
  464.     
  465.         case DPN_MSGID_CREATE_PLAYER:
  466.         {
  467.             PDPNMSG_CREATE_PLAYER   pCreatePlayerMsg;
  468.             DWORD                   dwSize = 0;
  469.             DPN_PLAYER_INFO*        pdpPlayerInfo = NULL;
  470.  
  471.             pCreatePlayerMsg = (PDPNMSG_CREATE_PLAYER)pMsgBuffer;
  472.  
  473.             // check to see if we are the player being created
  474.             hr = g_pDP->GetPeerInfo(pCreatePlayerMsg->dpnidPlayer, pdpPlayerInfo, &dwSize, 0);
  475.  
  476.             if( FAILED( hr) && hr != DPNERR_BUFFERTOOSMALL)
  477.             {
  478.                 printf("Failed GetPeerInfo:  0x%X\n", hr);
  479.                 return hr;
  480.             }
  481.  
  482.             pdpPlayerInfo = (DPN_PLAYER_INFO*) new BYTE[dwSize];
  483.             ZeroMemory(pdpPlayerInfo, dwSize);
  484.             pdpPlayerInfo->dwSize = sizeof(DPN_PLAYER_INFO);
  485.  
  486.             if( FAILED( hr = g_pDP->GetPeerInfo(pCreatePlayerMsg->dpnidPlayer, pdpPlayerInfo, &dwSize, 0 ) ) )
  487.             {
  488.                 printf("Failed GetPeerInfo:  0x%X\n", hr);
  489.                 goto Error_DPN_MSGID_CREATE_PLAYER;
  490.             }
  491.  
  492.             if( pdpPlayerInfo->dwPlayerFlags & DPNPLAYER_LOCAL)
  493.                 g_dpnidLocalPlayer = pCreatePlayerMsg->dpnidPlayer;
  494.  
  495. Error_DPN_MSGID_CREATE_PLAYER:
  496.             SAFE_DELETE_ARRAY(pdpPlayerInfo);
  497.             break;
  498.         }
  499.     }
  500.  
  501.     return hr;
  502. }
  503.  
  504.  
  505.  
  506.  
  507. //-----------------------------------------------------------------------------
  508. // Name: LobbyAppMessageHandler
  509. // Desc: Handler for DirectPlay lobby messages
  510. //-----------------------------------------------------------------------------
  511. HRESULT WINAPI LobbyAppMessageHandler(PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer)
  512. {
  513.     HRESULT     hr = S_OK;
  514.  
  515.     switch (dwMessageId)
  516.     {
  517.         case DPL_MSGID_CONNECT:
  518.         {
  519.             PDPL_MESSAGE_CONNECT        pConnectMsg;
  520.             PDPL_CONNECTION_SETTINGS    pSettings;
  521.  
  522.             pConnectMsg = (PDPL_MESSAGE_CONNECT)pMsgBuffer;
  523.             pSettings = pConnectMsg->pdplConnectionSettings;
  524.  
  525.             // Register the lobby with directplay so we get automatic notifications
  526.             hr = g_pDP->RegisterLobby(pConnectMsg->hConnectId, g_pLobbyApp, DPNLOBBY_REGISTER);
  527.             break;
  528.         }
  529.     }
  530.     return hr;
  531. }
  532.  
  533.  
  534.  
  535.  
  536. //-----------------------------------------------------------------------------
  537. // Name: EnumDirectPlayHosts()
  538. // Desc: Enumerates the hosts
  539. //-----------------------------------------------------------------------------
  540. HRESULT EnumDirectPlayHosts()
  541. {
  542.     HRESULT                 hr = S_OK;
  543.     WCHAR                   wszHost[128];
  544.     DPN_APPLICATION_DESC    dpAppDesc;
  545.     WCHAR*                  pwszURL = NULL;
  546.  
  547.     // Prompt for the hostname/ip
  548.     printf("\nPlease enter the IP address of host:\n");
  549.     wscanf(L"%ls", wszHost);
  550.  
  551.     if( FAILED( hr = CreateHostAddress(wszHost ) ) )
  552.     {
  553.         printf("Failed Creating Host Address:  0x%X\n", hr);
  554.         goto LCleanup;
  555.     }
  556.  
  557.     // Now set up the Application Description
  558.     ZeroMemory(&dpAppDesc, sizeof(DPN_APPLICATION_DESC));
  559.     dpAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  560.     dpAppDesc.guidApplication = g_guidApp;
  561.  
  562.     // We now have the host address so lets enum
  563.     if( FAILED( hr = g_pDP->EnumHosts( &dpAppDesc,            // pApplicationDesc
  564.                                        g_pHostAddress,     // pdpaddrHost
  565.                                        g_pDeviceAddress,   // pdpaddrDeviceInfo
  566.                                        NULL, 0,            // pvUserEnumData, size
  567.                                        4,                  // dwEnumCount
  568.                                        0,                  // dwRetryInterval
  569.                                        0,                  // dwTimeOut
  570.                                        NULL,               // pvUserContext
  571.                                        NULL,               // pAsyncHandle
  572.                                        DPNENUMHOSTS_SYNC ) ) )// dwFlags
  573.     {
  574.         printf("Failed Enumerating the Hosts:  0x%X\n", hr);
  575.         goto LCleanup;
  576.     }
  577.  
  578. LCleanup:
  579.     return hr;
  580. }
  581.  
  582.  
  583.  
  584.  
  585. //-----------------------------------------------------------------------------
  586. // Name: CreateDeviceAddress()
  587. // Desc: Creates a device address
  588. //-----------------------------------------------------------------------------
  589. HRESULT CreateDeviceAddress()
  590. {
  591.     HRESULT         hr = S_OK;
  592.  
  593.     // Create our IDirectPlay8Address Device Address
  594.     if( FAILED( hr = CoCreateInstance(CLSID_DirectPlay8Address, NULL,
  595.                                     CLSCTX_INPROC_SERVER,
  596.                                     IID_IDirectPlay8Address,
  597.                                     (LPVOID*) &g_pDeviceAddress ) ) )
  598.     {
  599.         printf("Failed Creating the IDirectPlay8Address Object:  0x%X\n", hr);
  600.         goto LCleanup;
  601.     }
  602.     
  603.     // Set the SP for our Device Address
  604.     if( FAILED( hr = g_pDeviceAddress->SetSP(&CLSID_DP8SP_TCPIP ) ) )
  605.     {
  606.         printf("Failed Setting the Service Provider:  0x%X\n", hr);
  607.         goto LCleanup;
  608.     }
  609.  
  610. LCleanup:
  611.     return hr;
  612. }
  613.  
  614.  
  615.  
  616.  
  617. //-----------------------------------------------------------------------------
  618. // Name: CreateHostAddress()
  619. // Desc: Creates a host address
  620. //-----------------------------------------------------------------------------
  621. HRESULT CreateHostAddress(WCHAR* pwszHost)
  622. {
  623.     HRESULT         hr = S_OK;
  624.  
  625.     // Create our IDirectPlay8Address Host Address
  626.     if( FAILED( hr = CoCreateInstance(CLSID_DirectPlay8Address, NULL,
  627.                                     CLSCTX_INPROC_SERVER,
  628.                                     IID_IDirectPlay8Address,
  629.                                     (LPVOID*) &g_pHostAddress ) ) )
  630.     {
  631.         printf("Failed Creating the IDirectPlay8Address Object:  0x%X\n", hr);
  632.         goto LCleanup;
  633.     }
  634.     
  635.     // Set the SP for our Host Address
  636.     if( FAILED( hr = g_pHostAddress->SetSP(&CLSID_DP8SP_TCPIP ) ) )
  637.     {
  638.         printf("Failed Setting the Service Provider:  0x%X\n", hr);
  639.         goto LCleanup;
  640.     }
  641.  
  642.     // Set the hostname into the address
  643.     if( FAILED( hr = g_pHostAddress->AddComponent(DPNA_KEY_HOSTNAME, pwszHost,
  644.                                                     2*(wcslen(pwszHost) + 1), /*bytes*/
  645.                                                     DPNA_DATATYPE_STRING ) ) )
  646.     {
  647.         printf("Failed Adding Hostname to Host Address:  0x%X\n", hr);
  648.         goto LCleanup;
  649.     }
  650.  
  651. LCleanup:
  652.     return hr;
  653. }
  654.  
  655.  
  656.  
  657.  
  658. //-----------------------------------------------------------------------------
  659. // Name: HostSession()
  660. // Desc: Host a DirectPlay session
  661. //-----------------------------------------------------------------------------
  662. HRESULT HostSession()
  663. {
  664.     HRESULT                 hr = S_OK;
  665.     DPN_APPLICATION_DESC    dpAppDesc;
  666.     WCHAR                   wszSession[128];
  667.  
  668.  
  669.     // Prompt the user for the session name
  670.     printf("\nPlease Enter a Session Name.\n");
  671.     wscanf(L"%ls", wszSession);
  672.  
  673.     // Now set up the Application Description
  674.     ZeroMemory(&dpAppDesc, sizeof(DPN_APPLICATION_DESC));
  675.     dpAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  676.     dpAppDesc.guidApplication = g_guidApp;
  677.     dpAppDesc.pwszSessionName = wszSession;
  678.     dpAppDesc.dwFlags = DPNSESSION_MIGRATE_HOST;
  679.  
  680.     // We are now ready to host the app
  681.     if( FAILED( hr = g_pDP->Host(&dpAppDesc,             // AppDesc
  682.                                 &g_pDeviceAddress, 1,   // Device Address
  683.                                 NULL, NULL,             // Reserved
  684.                                 NULL,                   // Player Context
  685.                                 0 ) ) )                    // dwFlags
  686.     {
  687.         printf("Failed Hosting:  0x%X\n", hr);
  688.         goto LCleanup;
  689.     }
  690.     else
  691.     {
  692.         printf("Currently Hosting...\n");
  693.     }
  694.  
  695.  
  696. LCleanup:
  697.     return hr;
  698. }
  699.  
  700.  
  701.  
  702.  
  703. //-----------------------------------------------------------------------------
  704. // Name: ConnectToSession()
  705. // Desc: Connects to a DirectPlay session
  706. //-----------------------------------------------------------------------------
  707. HRESULT ConnectToSession()
  708. {
  709.     HRESULT                     hr = E_FAIL;
  710.     DPN_APPLICATION_DESC        dpnAppDesc;
  711.     IDirectPlay8Address*        pHostAddress = NULL;
  712.  
  713.  
  714.     ZeroMemory(&dpnAppDesc, sizeof(DPN_APPLICATION_DESC));
  715.     dpnAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  716.     dpnAppDesc.guidApplication = g_guidApp;
  717.  
  718.     // Simply connect to the first one in the list
  719.     EnterCriticalSection(&g_csHostList);
  720.  
  721.     if( g_pHostList && SUCCEEDED(hr = g_pHostList->pHostAddress->Duplicate(&pHostAddress ) ) )
  722.     {
  723.         hr = g_pDP->Connect(&dpnAppDesc,        // pdnAppDesc
  724.                             pHostAddress,       // pHostAddr
  725.                             g_pDeviceAddress,   // pDeviceInfo
  726.                             NULL,               // pdnSecurity
  727.                             NULL,               // pdnCredentials
  728.                             NULL, 0,            // pvUserConnectData/Size
  729.                             NULL,               // pvPlayerContext
  730.                             NULL,               // pvAsyncContext
  731.                             NULL,               // pvAsyncHandle
  732.                             DPNCONNECT_SYNC);   // dwFlags
  733.  
  734.         if( FAILED( hr))
  735.             printf("Failed Connecting to Host:  0x%x\n", hr);
  736.     }
  737.     else
  738.     {
  739.         printf("Failed Duplicating Host Address:  0x%x\n", hr);
  740.     }
  741.  
  742.     LeaveCriticalSection(&g_csHostList);
  743.  
  744.     SAFE_RELEASE(pHostAddress);
  745.     return hr;
  746. }
  747.  
  748.  
  749.  
  750.  
  751. //-----------------------------------------------------------------------------
  752. // Name: SendDirectPlayMessage()
  753. // Desc: Sends a DirectPlay message to all players
  754. //-----------------------------------------------------------------------------
  755. HRESULT SendDirectPlayMessage()
  756. {
  757.     HRESULT         hr = S_OK;
  758.     DPN_BUFFER_DESC dpnBuffer;
  759.     WCHAR           wszData[256];
  760.  
  761.     // Get the data from the user
  762.     printf("\nPlease Enter a String.\n");
  763.     wscanf(L"%ls", wszData);
  764.  
  765.     dpnBuffer.pBufferData = (BYTE*) wszData;
  766.     dpnBuffer.dwBufferSize = 2 * (wcslen(wszData) + 1);
  767.  
  768.     if( FAILED( hr = g_pDP->SendTo(DPNID_ALL_PLAYERS_GROUP,  // dpnid
  769.                                     &dpnBuffer,             // pBufferDesc
  770.                                     1,                      // cBufferDesc
  771.                                     0,                      // dwTimeOut
  772.                                     NULL,                   // pvAsyncContext
  773.                                     NULL,                   // pvAsyncHandle
  774.                                     DPNSEND_SYNC |
  775.                                     DPNSEND_NOLOOPBACK ) ) )   // dwFlags
  776.     {
  777.         printf("Failed Sending Data:  0x%x\n", hr);
  778.     }
  779.     return hr;
  780. }
  781.  
  782.  
  783.  
  784.  
  785. //-----------------------------------------------------------------------------
  786. // Name: Register()
  787. // Desc: Register app as lobby launchable
  788. //-----------------------------------------------------------------------------
  789. HRESULT Register()
  790. {
  791.     HRESULT             hr = S_OK;
  792.     DPL_PROGRAM_DESC    dplDesc;
  793.     WCHAR*              pwszPath = NULL;
  794.     WCHAR*              pwszExecutable = NULL;
  795.     int                 i;
  796.  
  797.     ZeroMemory(&dplDesc, sizeof(DPL_PROGRAM_DESC));
  798.     dplDesc.dwSize = sizeof(DPL_PROGRAM_DESC);
  799.     dplDesc.guidApplication = g_guidApp;
  800.  
  801.     // We need to parse out the path and the exe name from the input value
  802.     for (i = wcslen(g_wszPath); i >=0 && g_wszPath[i] != L'\\'; i--);
  803.  
  804.     pwszPath = new WCHAR[i + 1];
  805.  
  806.     if( pwszPath == NULL)
  807.     {
  808.         printf("Failed parsing path.");
  809.         hr = E_FAIL;
  810.         goto LCleanup;
  811.     }
  812.     
  813.     wcsncpy(pwszPath, g_wszPath, i);
  814.     pwszPath[i] = L'\0';
  815.     pwszExecutable = g_wszPath + i + 1;
  816.  
  817.     dplDesc.pwszApplicationName = pwszExecutable;
  818.     dplDesc.pwszExecutableFilename = pwszExecutable;
  819.     dplDesc.pwszExecutablePath = pwszPath;
  820.  
  821.     hr = g_pLobbyApp->RegisterProgram(&dplDesc, 0);
  822. LCleanup:
  823.     SAFE_DELETE_ARRAY(pwszPath);
  824.  
  825.     return hr;
  826. }
  827.  
  828.  
  829.  
  830.  
  831. //-----------------------------------------------------------------------------
  832. // Name: UnRegister()
  833. // Desc: Unregister app as lobby launchable
  834. //-----------------------------------------------------------------------------
  835. HRESULT UnRegister()
  836. {
  837.     HRESULT     hr = S_OK;
  838.  
  839.     hr = g_pLobbyApp->UnRegisterProgram(&g_guidApp, 0);
  840.  
  841.     return hr;
  842. }
  843.  
  844.  
  845.  
  846.  
  847. //-----------------------------------------------------------------------------
  848. // Name: LobbyLaunch()
  849. // Desc: Host or connect to session based on lobby launch settings
  850. //-----------------------------------------------------------------------------
  851. HRESULT LobbyLaunch()
  852. {
  853.     HRESULT                     hr = S_OK;
  854.     DPL_CONNECTION_SETTINGS*    pSettings = NULL;
  855.     DWORD                       dwSettingsSize = 0;
  856.  
  857.     // Get the lobby connection data
  858.     // First see how big a buffer we need
  859.     hr = g_pLobbyApp->GetConnectionSettings(g_hLobbyHandle, pSettings, &dwSettingsSize, 0);
  860.  
  861.     if( hr != DPNERR_BUFFERTOOSMALL)
  862.     {
  863.         printf("Failed GetConnectionSettings:  0x%x\n", hr);
  864.         goto LCleanup;
  865.     }
  866.  
  867.     pSettings = (DPL_CONNECTION_SETTINGS*) new BYTE[dwSettingsSize];
  868.  
  869.     if( pSettings == NULL)
  870.     {
  871.         printf("Failed Allocating Buffer:  0x%x\n");
  872.         hr = E_FAIL;
  873.         goto LCleanup;
  874.     }
  875.  
  876.     if( FAILED( hr = g_pLobbyApp->GetConnectionSettings(g_hLobbyHandle, pSettings, &dwSettingsSize, 0 ) ) )
  877.     {
  878.         printf("Failed GetConnectionSettings:  0x%x\n", hr);
  879.         goto LCleanup;
  880.     }
  881.  
  882.     if( pSettings->dwFlags & DPLCONNECTSETTINGS_HOST)
  883.     {
  884.         // We are to host the game
  885.         if( FAILED( hr = g_pDP->Host(&pSettings->dpnAppDesc,        // dpnAppDesc
  886.                                     pSettings->ppdp8DeviceAddresses,// prgpDeviceInfo
  887.                                     pSettings->cNumDeviceAddresses, // cDeviceInfo
  888.                                     NULL, NULL,                     // Security
  889.                                     NULL,                           // pvPlayerContext
  890.                                     0 ) ) )                         // dwFlags
  891.         {
  892.             printf("Failed Host:  0x%x\n", hr);
  893.             goto LCleanup;
  894.         }
  895.     }
  896.     else
  897.     {
  898.         // We need to connect
  899.         if( FAILED( hr = g_pDP->Connect(&pSettings->dpnAppDesc,             // pdnAppDesc
  900.                                         pSettings->pdp8HostAddress,         // pHostAddr
  901.                                         pSettings->ppdp8DeviceAddresses[0], // pDeviceInfo
  902.                                         NULL, NULL,                         // Security
  903.                                         NULL, 0,                            // pvUserConnectData/Size
  904.                                         NULL,                               // pvPlayerContext
  905.                                         NULL, NULL,                         // pvAsyncContext/Handle
  906.                                         DPNCONNECT_SYNC ) ) )               // dwFlags
  907.         {
  908.             printf("Failed Lobby App Connect:  0x%x\n", hr);
  909.             goto LCleanup;
  910.         }
  911.  
  912.     }
  913. LCleanup:
  914.     if( pSettings)
  915.     {
  916.         SAFE_RELEASE(pSettings->pdp8HostAddress);
  917.  
  918.         for (DWORD dwIndex = 0; dwIndex < pSettings->cNumDeviceAddresses; dwIndex++)
  919.         {
  920.             SAFE_RELEASE(pSettings->ppdp8DeviceAddresses[dwIndex]);
  921.         }
  922.     }
  923.     SAFE_DELETE_ARRAY(pSettings);
  924.     return hr;
  925. }
  926.  
  927.  
  928.  
  929.  
  930. //-----------------------------------------------------------------------------
  931. // Name: CleanupDirectPlay()
  932. // Desc: Cleanup DirectPlay
  933. //-----------------------------------------------------------------------------
  934. void CleanupDirectPlay()
  935. {
  936.     HOST_NODE* pHostNode = NULL;
  937.     HOST_NODE* pHostNodetmp = NULL;
  938.  
  939.     // Cleanup DirectPlay
  940.     if( g_pDP)
  941.         g_pDP->Close(0);
  942.  
  943.     if( g_pLobbyApp)
  944.         g_pLobbyApp->Close(0);
  945.  
  946.     // Clean up Host list
  947.     EnterCriticalSection(&g_csHostList);
  948.     
  949.     pHostNode = g_pHostList;
  950.     while( pHostNode != NULL )
  951.     {       
  952.         SAFE_RELEASE(pHostNode->pHostAddress);
  953.         SAFE_DELETE(pHostNode->pAppDesc);
  954.         SAFE_DELETE(pHostNode->pwszSessionName);
  955.  
  956.         pHostNodetmp = pHostNode;
  957.         pHostNode    = pHostNode->pNext;
  958.         SAFE_DELETE(pHostNodetmp);
  959.     }
  960.  
  961.     LeaveCriticalSection(&g_csHostList);
  962.  
  963.     SAFE_RELEASE(g_pDeviceAddress);
  964.     SAFE_RELEASE(g_pHostAddress);
  965.     SAFE_RELEASE(g_pDP);
  966.     SAFE_RELEASE(g_pLobbyApp);
  967.     SAFE_DELETE_ARRAY(g_wszPath);
  968.  
  969.     DeleteCriticalSection(&g_csHostList);
  970. }
  971.